package com.songlanyun.modules.usergains.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.enums.*;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.utils.DateUtils;
import com.songlanyun.common.utils.custom.DateCustomUtils;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.account.dao.HandlingFeesDao;
import com.songlanyun.modules.account.entity.AccountEntity;
import com.songlanyun.modules.account.entity.UserIdentityAssetEntity;
import com.songlanyun.modules.account.entity.UserVerifiedEntity;
import com.songlanyun.modules.account.service.AccountService;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.account.service.UserInfoService;
import com.songlanyun.modules.account.service.UserVerifiedService;
import com.songlanyun.modules.aridroprecord.entity.AridropRecordEntity;
import com.songlanyun.modules.aridroprecord.service.AridropRecordService;
import com.songlanyun.modules.distributionconfig.entity.DistributionConfig;
import com.songlanyun.modules.distributionconfig.service.DistributionConfigService;
import com.songlanyun.modules.exception.MemberException;
import com.songlanyun.modules.gains.entity.ShopOrderGains;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.offlineorder.service.OfflineOrderService;
import com.songlanyun.modules.pointconfig.entity.PointConfig;
import com.songlanyun.modules.pointconfig.service.PointConfigService;
import com.songlanyun.modules.pointgiveaway.service.PointGiveAwayService;
import com.songlanyun.modules.pointtobalace.service.PointToBalanceRecordService;
import com.songlanyun.modules.user.entity.SysUserEntity;
import com.songlanyun.modules.usergains.entity.UserOrderGains;
import com.songlanyun.modules.usergains.model.*;
import com.songlanyun.modules.usergains.service.IDistributionHandle;
import com.songlanyun.modules.usergains.service.UserBillService;
import com.songlanyun.modules.withdraw.service.WithdrawService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.usergains.dao.UserOrderGainsDao;
import com.songlanyun.modules.usergains.service.UserOrderGainsService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("userOrderGainsService")
public class UserOrderGainsServiceImpl extends ServiceImpl<UserOrderGainsDao, UserOrderGains> implements UserOrderGainsService, IDistributionHandle {





    @Autowired
    private WithdrawService withdrawService;


    @Autowired
    private AccountService accountService;

    @Autowired
    private UserBillServiceImpl userBillService;


    @Autowired
    private UserIdentityAssetService userIdentityAssetService;

    @Autowired
    private UserVerifiedService userVerifiedService;


    @Autowired
    private IntegralRecordService integralRecordService;


    @Autowired
    private AridropRecordService aridropRecordService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private PointConfigService pointConfigService;


    @Autowired
    private PointToBalanceRecordService pointToBalanceRecordService;


    @Autowired
    private PointGiveAwayService pointGiveAwayService;

    @Autowired
    private OfflineOrderService offlineOrderService;

    @Autowired
    private HandlingFeesDao handlingFeesDao;


    @Override
    public UserOrderGains create(UserOrderGains entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.insert(entity);
        return entity;
    }

    @Override
    public UserOrderGains modify(UserOrderGains entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Long shopId = MapUtil.getLong(params, "shop_id");
        String mobile = MapUtil.getStr(params, "mobile");
        String orderCode = MapUtil.getStr(params, "order_code");
        Integer status = MapUtil.getInt(params, "status");
        Integer userOrderGainsType = MapUtil.getInt(params, "user_order_gains_type");
        String startDate = MapUtil.getStr(params, "start_date");
        String endDate = MapUtil.getStr(params, "end_date");
        Long userId = MapUtil.getLong(params, "user_id");
        Long childOrderId = MapUtil.getLong(params, "child_order_id");

        LambdaQueryWrapper<UserOrderGains> wrapper = new LambdaQueryWrapper<>();

        if (shopId != null) {
            wrapper.eq(UserOrderGains::getShopId, shopId);
        }

        if (userId != null) {
            wrapper.eq(UserOrderGains::getDistributionUserId, userId);
//            wrapper.in(UserOrderGains::getDistributionComputer, DistributionConstant.DistributionComputer.COMMON,
//                    DistributionConstant.DistributionComputer.SHARE);
        }

        if (StringUtils.isNotBlank(mobile)) {
            wrapper.like(UserOrderGains::getDistributionUserMobile, mobile);
        }

        if (StringUtils.isNotBlank(orderCode)) {
            wrapper.like(UserOrderGains::getOrderCode, orderCode);
        }

        if(userOrderGainsType!=null && userOrderGainsType >-1)
        {
            wrapper.eq(UserOrderGains::getUserOrderGainsType, userOrderGainsType);
        }

        if (status != null) {
            switch (status) {
                //未完成
                case 1:
                    wrapper.eq(UserOrderGains::getAbleSettlement, false);
                    break;
                //已完成,未结算
                case 2:
                    wrapper.eq(UserOrderGains::getAbleSettlement, true);
                    wrapper.eq(UserOrderGains::getSettlement, false);
                    break;
                //已结算
                case 3:
                    wrapper.eq(UserOrderGains::getSettlement, true);
                    break;
            }
        }

        //应结算时间
        if (StringUtils.isNotBlank(startDate)) {
            wrapper.ge(UserOrderGains::getShouldSettlementTime, DateUtils.stringToDate(startDate, DateUtils.DATE_PATTERN));
        }

        if (StringUtils.isNotBlank(endDate)) {
            Date end = DateUtils.addDateDays(DateUtils.stringToDate(endDate, DateUtils.DATE_PATTERN), 1);
            wrapper.le(UserOrderGains::getShouldSettlementTime, end);
        }

        if (childOrderId != null) {
            wrapper.eq(UserOrderGains::getChildOrderId, childOrderId);
        }

        wrapper.orderByDesc(UserOrderGains::getCreateTime).orderByDesc(UserOrderGains::getChildOrderId);
        IPage<UserOrderGains> page = this.page(
                new Query<UserOrderGains>().getPage(params), wrapper);
        page.getRecords().forEach(o -> {
            o.loadUserBankCard();
            o.loadUserInfo();
            o.loadDistributionUserName();//分佣人昵称
            o.loadShopAbleGains();
        });
        return new PageUtils(page);
    }

    @Override
    public List<UserOrderGainsVo> queryList(Map<String, Object> params) {

        String startDate = MapUtil.getStr(params, "start_date");
        String endDate = MapUtil.getStr(params, "end_date");
        if (StringUtils.isNotBlank(startDate)) {
            params.put("start_date", DateUtils.format(DateUtils.stringToDate(startDate, DateUtils.DATE_PATTERN), DateUtils.DATE_TIME_PATTERN));
        }

        if (StringUtils.isNotBlank(endDate)) {
            params.put("end_date", DateUtils.format(DateUtils.addDateDays(DateUtils.stringToDate(endDate, DateUtils.DATE_PATTERN), 1), DateUtils.DATE_TIME_PATTERN));
        }
        return this.baseMapper.queryList(params);
    }

    @Override
    public UserOrderGains createGains(ShopOrderGains shopOrderGains, UserOrderGainsTo to) {
        UserOrderGains entity = new UserOrderGains();
        entity.setOrderId(shopOrderGains.getOrderId());
        entity.setOrderCode(shopOrderGains.getOrderCode());
        entity.setChildOrderId(shopOrderGains.getChildOrderId());
        entity.setGoodsType(shopOrderGains.getGoodsType());
        entity.setGoodsId(shopOrderGains.getGoodsId());
        entity.setMarketingType(shopOrderGains.getMarketingType());
        entity.setShopId(shopOrderGains.getShopId());
        entity.setShopName(shopOrderGains.getShopName());
        entity.setGoodsTitle(shopOrderGains.getGoodsTitle());
        entity.setExistsRefund(shopOrderGains.getExistsRefund());
        entity.setUserId(shopOrderGains.getUserId());
        entity.setShortGoodsTitle(shopOrderGains.getShortGoodsTitle());
        entity.setRealPrice(shopOrderGains.getRealPrice());
        entity.setSalePrice(shopOrderGains.getSalePrice());
        entity.setGoodsImg(shopOrderGains.getGoodsImg());
        entity.setTotalRealPrice(shopOrderGains.getTotalRealPrice());
        entity.setShipmentMode(shopOrderGains.getShipmentMode());
        entity.setUnit(shopOrderGains.getUnit());
        entity.setSkuBarCode(shopOrderGains.getSkuBarCode());
        entity.setSkuHashCode(shopOrderGains.getSkuHashCode());
        entity.setSkuSetName(shopOrderGains.getSkuSetName());
        entity.setNumber(shopOrderGains.getNumber());
        entity.setTotalReduced(shopOrderGains.getTotalReduced());
        entity.setFirstOrderReduced(shopOrderGains.getFirstOrderReduced());
        entity.setCost(shopOrderGains.getCost());
        entity.setTotalCost(shopOrderGains.getTotalCost());
        entity.setSingleGoodsId(shopOrderGains.getSingleGoodsId());
        entity.setConsumptionValue(shopOrderGains.getConsumptionValue());
        entity.setGains(to.getGains());
        entity.setRefundDeduct(BigDecimal.ZERO);
        entity.computeAbleGains();
        entity.setSettlement(false);
        entity.setDistributionUserId(to.getVo().getId());
        entity.setDistributionUserMobile(to.getVo().getMobile());
        entity.setDistributionComputer(to.getDistributionComputer());
        entity.setDistributionUserRoleCode(to.getVo().getRoleCode());
        entity.setDistributionUserRoleName(to.getVo().getRoleName());
        entity.setDistributionType(to.getDistributionType());
        entity.setEnvRemark(to.getEnvRemark());
        entity.setProxyGoods(shopOrderGains.getProxyGoods());
        entity.setChannelType(shopOrderGains.getChannelType());
        entity.setGiftType(shopOrderGains.getGiftType());
        entity.setSettlementRemark("");
        entity.setAbleSettlement(false);
        entity.setShopGainsId(shopOrderGains.getId());
        entity.setUserOrderGainsType(to.getUserOrderGainsType());
        entity.setRatio(to.getRatio());
        return this.create(entity);
    }

    @Resource(name = "generalGoodsDistribution")
    private IDistributionHandle generalGoodsDistribution;


    @Resource(name = "activatingGoodsDistribution")
    private IDistributionHandle activatingGoodsDistribution;

    @Override
    public List<UserOrderGains> handle(ShopOrderGains shopOrderGains) {

        List<UserOrderGains> list = new ArrayList<>();
        List<UserOrderGains> other = new ArrayList<>();
        if(shopOrderGains.getAreaFeature().equals(GoodsConstant.AreaFeature.ACTIVATING)) {
            activatingGoodsDistribution.handle(shopOrderGains);
        }
        else {
            other = generalGoodsDistribution.handle(shopOrderGains);
        }

        if (other.size() > 0) {
            list.addAll(other);
        }

        return list;
    }


    /**
     * 计算退款影响值
     *
     * @param obj
     */
    @Override
    public void refundDeduct(ShopOrderGains obj) {
        List<UserOrderGains> list = obj.loadUserOrderGainsList(true);
        list.forEach(userOrderGains -> {

            userOrderGains.setExistsRefund(true);
            userOrderGains.computeRefundDeduct(obj);
            this.modify(userOrderGains);

        });
    }

    /**
     * 根据商家所得获取会员分佣所得
     *
     * @param shopId
     * @param shopGainsId
     * @return
     */
    @Override
    public List<UserOrderGains> loadByShopGains(Long shopId, Long shopGainsId) {
        return this.list(new LambdaQueryWrapper<UserOrderGains>()
                .eq(UserOrderGains::getShopId, shopId)
                .eq(UserOrderGains::getShopGainsId, shopGainsId)
                .orderByAsc(UserOrderGains::getDistributionUserId)
        );
    }


    @Override
    public void manualSettlement(Long shopId, SettlementUserOrderGainsDTO dto) {
        for (Long id : dto.getIds()) {
            UserOrderGains userOrderGains = loadByShopIdAndId(shopId, id);

            if (userOrderGains != null
                    && userOrderGains.getAbleSettlement()
                    && !DistributionConstant.DistributionComputer.COMMON.equals(userOrderGains.getDistributionComputer())) {
                userOrderGains.setSettlementRemark(dto.getRemark());
                userOrderGains.setSettlement(true);
                userOrderGains.setSettlementTime(new Date());
                this.modify(userOrderGains);
            }
        }
    }

    @Override
    public UserOrderGainsStatisticsVo slimStatistics(Long userId) {

        UserOrderGainsStatisticsVo vo = new UserOrderGainsStatisticsVo();
        vo.setWeekUserOrderGainsNum(this.baseMapper.selectCount(new LambdaQueryWrapper<UserOrderGains>()
                .eq(UserOrderGains::getDistributionUserId, userId)
                .ge(UserOrderGains::getCreateTime, DateCustomUtils.getWeekStart(new Date()))
                .le(UserOrderGains::getCreateTime, DateUtils.addDateDays(DateCustomUtils.getWeekEnd(new Date()),1))));


        vo.setMonthUserOrderGainsNum(this.baseMapper.selectCount(new LambdaQueryWrapper<UserOrderGains>()
                .eq(UserOrderGains::getDistributionUserId, userId)
                .ge(UserOrderGains::getCreateTime, DateCustomUtils.getMonthStart(new Date()))
                .le(UserOrderGains::getCreateTime, DateUtils.addDateDays(DateCustomUtils.getMonthEnd(new Date()),1))));
        return vo;
    }

    @Override
    public UserOrderGainsStatisticsVo statistics(Long userId) {
        UserOrderGainsStatisticsVo vo = new UserOrderGainsStatisticsVo();
        vo.setPullNewValue(this.baseMapper.pullNewStatistics(userId));
        vo.setExtensionValue(this.baseMapper.extensionStatistics(userId));
        vo.setWithdrawalNum(withdrawService.count(userId));
        return vo;
    }

    @Override
    public BigDecimal loadByWaitAccount(Long userId) {
        return this.baseMapper.loadByWaitAccount(userId);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BigDecimal givePointDecCommissionAble(PointConfig config, BigDecimal allActivationUseCommissionAble, BigDecimal sum, AccountEntity entity) {
//        Date lastActivatingTime = entity.getLastActivatingTime();
//        Date date1 = DateUtils.addDateDays(lastActivatingTime, config.getActivationPeriodDay());
//        if(date1.compareTo(new Date())<=0)
//        {
//            //激活过期要修改激活状态
//            entity.setActivating(false);
//            accountService.modify(entity);
//            return sum;
//        }



        BigDecimal commissionAble = userIdentityAssetService.getCommissionAble(entity.getId());
        //计算出应该给这个会员空投的积分是多少
        BigDecimal airdropPoint = MathUtils.setScaleDown(config.getEveryDayPutIntPoint().doubleValue() * commissionAble.doubleValue() / allActivationUseCommissionAble.doubleValue(), 8);

        UserVerifiedEntity userVerifiedEntity = userVerifiedService.loadById(entity.getId(), false);
        AridropRecordEntity aridropRecordEntity = new AridropRecordEntity();
        aridropRecordEntity.setUserId(entity.getId());
        aridropRecordEntity.setMobile(entity.getMobile());
        aridropRecordEntity.setRealName(ObjectUtil.isNull(userVerifiedEntity)?"未实名":userVerifiedEntity.getRealName());
        aridropRecordEntity.setGivePoint(airdropPoint);
        aridropRecordEntity.setCurrentCommissionAble(commissionAble);
        aridropRecordEntity.setCurrentAirdropTotalPoint(config.getEveryDayPutIntPoint());
        aridropRecordEntity.setCurrentTotalCommissionAble(allActivationUseCommissionAble);
        aridropRecordService.create(aridropRecordEntity);


        IntegralRecord integralRecord = new IntegralRecord(entity.getId(), airdropPoint, IntegralConstant.InnerMode.CONSUMPTION_VALUE_FREED_POINT,
                IntegralConstant.IntegralModelType.CONSUMPTION_VALUE_FREED_POINT, entity.getId(), "贡献值释放积分");
        integralRecordService.inner(integralRecord);

        sum = MathUtils.setScaleDown(sum.doubleValue() + airdropPoint.doubleValue(),8);
        //计算应消耗的贡献值是多少
        BigDecimal consumptionValue = MathUtils.setScale(airdropPoint.doubleValue() * config.getPointPrice().doubleValue(), 2);

        UserIdentityAssetEntity userIdentity = userIdentityAssetService.loadByIdForLock(entity.getId(), true);
        if(consumptionValue.compareTo(userIdentity.getCommissionAble())>0)
        {
            consumptionValue = userIdentity.getCommissionAble();
        }

        userBillService.outBill(entity.getId(),
                "贡献值释放积分",
                UserBillConstant.OuterMode.CONSUMPTION_RELEASES_POINTS,
                consumptionValue,
                "","系统");

        return sum;
    }

//    public static void main(String[] args) {
//        BigDecimal sum = MathUtils.setScaleDown(BigDecimal.valueOf(931.00000000).doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        sum = MathUtils.setScaleDown(sum.doubleValue() + BigDecimal.valueOf(931.00000000).doubleValue(),8);
//        System.out.println(sum);
//    }


    @Override
    public void updateCommission(SysUserEntity sysUserEntity, UpdateCommissionDTO dto) {
        AccountEntity account = accountService.getUserById(dto.getUserId(), true);
        UserIdentityAssetEntity userIdentityAssetEntity = userIdentityAssetService.loadByIdForLock(dto.getUserId(), true);
        //第二次需求提出这里不要实名认证
        //        UserVerifiedEntity userVerifiedEntity = userVerifiedService.loadById(dto.getUserId(), false);
//        if(ObjectUtil.isNull(userVerifiedEntity))
//        {
//            throw new RRException("该会员还没有做实名认证");
//        }
        if(!dto.getAdd())
        {
            if (userIdentityAssetEntity.getCommissionAble().compareTo(dto.getValue()) < 0) {//可提现所得是否充足
                    throw new RRException(MemberException.NOT_SUFFICIENT_FUNDS);
            }
            userBillService.outBill(dto.getUserId(),"平台后台扣减", UserBillConstant.OuterMode.ADMIN_DEV,dto.getValue(),"",sysUserEntity.getUsername());
        }
        else
        {
            userBillService.inBill(dto.getUserId(),"平台后台赠送", UserBillConstant.InnerMode.ADMIN_ADD,dto.getValue(),"",sysUserEntity.getUsername());
        }



    }

    @Override
    public AirdropStatisticsVo airdropStatistics() {
        BigDecimal allActivatingCommissionAble = userIdentityAssetService.countAllActivationUseCommissionAble();
        PointConfig config = pointConfigService.loadConfig(false);
        AirdropStatisticsVo airdropStatisticsVo = new AirdropStatisticsVo();
        airdropStatisticsVo.setPointPrice(config.getPointPrice());
        airdropStatisticsVo.setGiveTotalPoint(config.getGiveTotalPoint());
        airdropStatisticsVo.setAllActivatingCommissionAble(allActivatingCommissionAble);

        BigDecimal allHandlingFee = pointToBalanceRecordService.allHandlingFee();
        BigDecimal allHandlingFee2 = pointGiveAwayService.allHandlingFee();
        //提现的
        BigDecimal countHandlingFee = handlingFeesDao.selectCountHandlingFee();
        countHandlingFee = MathUtils.setScaleDown(countHandlingFee.doubleValue() / 0.7, 8);
        countHandlingFee = MathUtils.setScaleDown(countHandlingFee.doubleValue() * 0.3, 8);



        BigDecimal countShopConsumeIntegralAble = offlineOrderService.selectCountShopConsumeIntegralAble();
        BigDecimal decimal = MathUtils.setScaleDown(countShopConsumeIntegralAble.doubleValue() * 0.7, 8);

        allHandlingFee = MathUtils.setScaleDown(allHandlingFee.doubleValue() + allHandlingFee2.doubleValue(), 8);
        allHandlingFee = MathUtils.setScaleDown(allHandlingFee.doubleValue() + decimal.doubleValue(), 8);
        allHandlingFee = MathUtils.setScaleDown(allHandlingFee.doubleValue() + countHandlingFee.doubleValue(), 8);

        airdropStatisticsVo.setAllHandlingFee(allHandlingFee);

        airdropStatisticsVo.setAllPointCost(MathUtils.setScale((config.getGiveTotalPoint().doubleValue()-allHandlingFee.doubleValue())*config.getPointPrice().doubleValue(),8));
        return airdropStatisticsVo;
    }


    private UserOrderGains loadByShopIdAndId(Long shopId, Long id) {
        return this.getOne(new LambdaQueryWrapper<UserOrderGains>()
                .eq(UserOrderGains::getShopId, shopId)
                .eq(UserOrderGains::getId, id)
                .last("limit 1"));
    }


    public List<UserOrderGains> queryNotResultOrderGains(Long childOrderId){
        return this.list(new LambdaQueryWrapper<UserOrderGains>()
                .eq(UserOrderGains::getShopId, 9)
                .eq(UserOrderGains::getSettlement, 0)
                .eq(UserOrderGains::getAbleSettlement, 0)
                .gt(UserOrderGains::getCreateTime, "2024-05-14 13:00:12")
                .eq(UserOrderGains::getChildOrderId,childOrderId)
        );
    }

}
